
//: Playground - noun: a place where people can play

import UIKit

//: # swfit 读书笔记

//: ##   空合运算符 (??)
//: ###  a??b  a有值选 a ，反之选 b
let defaultColorName = "red"
var userDefinedColorName: String?   //默认值为 nil
var colorNameToUse = userDefinedColorName ?? defaultColorName

//: ## 区间运算符
//: * 闭区间 a...b  (a 到 b 全包括)
//: * 半闭区间运算符  a..<b (a 到 b 不包括b)

//: ## 字符串里面的特殊字符
//: * 转义字符\0(空字符)、\\(反斜线)、\t(水平制表符)、\n(换行符)、\r(回车“符)、\(双引号)、\'(单引号)

//: ## 访问和修改字符串
//: * 您可以使用 startIndex 和 endIndex 属性或者 index(before:) 、index(after:) 和 index(_:offsetBy:) 方法在任意一个确认的并遵循 Collection 协议的类型里面，如上文所示是使用在 String 中，您也可以使用在 Array、Dictionary 和 Set中。
//: ### 1. 字符串索引
var StringIndex = "qwa"
//: * startIndex 起始位置下标
print("startIndex - \(StringIndex.startIndex.encodedOffset)")
//: * endIndex 末尾位置下标的下一位
print("endIndex - \(StringIndex.endIndex.encodedOffset)")
//: * index(before:)
print("_____index(before:)____")
print(StringIndex[StringIndex.index(before: StringIndex.endIndex)])
//: * index(after:)
print("_____index(after:)____")
print(StringIndex[StringIndex.index(after: StringIndex.startIndex)])
//: * index(_:offsetBy:)
print("_____index(_:offsetBy:)____")
print(StringIndex[StringIndex.index(StringIndex.startIndex, offsetBy: 1)])

//: ### 使用 characters 属性的 indices 属性会创建一个包含全部索引的范围(Range)，用来在一个字符串中访问单个字符
print("______indices_______")
for index in StringIndex.characters.indices {
    print("\(StringIndex[index])")
}


//: ### note:您可以使用 insert(_:at:)、insert(contentsOf:at:)、remove(at:) 和 removeSubrange(_:) 方法在任意一个确认的并遵循 RangeReplaceableCollection 协议的类型里面，如上文所示是使用在 String 中，您也可以使用在 Array、Dictionary 和 Set 中。
//: ### 插入
//: ### 1.insert(_:at:) 在一个字符串的指定索引插入一个字符
print("______insert(_:at:)_______")
StringIndex.insert("*", at: StringIndex.startIndex)
print(StringIndex)
//: ### 2.insert(contentsOf:at:) 在一个字符串的指定索引插入一个段字符串
print("______insert(contentsOf:at:)_______")
StringIndex.insert(contentsOf: "zzp", at: StringIndex.endIndex)
print(StringIndex)

//: ### 删除
//: ### remove(at:)在一个字符串的指定索引删除一个字符
print("______remove(at:)_______")
StringIndex.remove(at: StringIndex.startIndex)
print(StringIndex)

//: ### removeSubrange(_:)  在一个字符串的指定索引删除一个子字符串
print("______removeSubrange(_:)_______")
let removeRange = StringIndex.index(StringIndex.endIndex, offsetBy: -3) ..< StringIndex.endIndex
StringIndex.removeSubrange(removeRange)
print(StringIndex)

//: ### 通过调用字符串的hasPrefix(_:)/hasSuffix(_:)方法来检查字符串是否拥有特定前缀/后缀，两个方法均接收一个String类型的参数，并返回一个布尔值。

//: ## 数组:元组的数据不能增删，但是修改还是可以的
//: ### 1.创建一个空数组
var someInts = [Int]()

//: ### 2.创建一个带有默认值的数组
var defalutValueArr = Array (repeating: "zzp", count: 3)



//: ### 3. 使用布尔属性isEmpty作为一个缩写形式去检查count属性是否为0
if someInts.isEmpty{
    print("someInts 是 空的")
}
//: ### 4.insert(_:at:)方法来在某个具体索引值之前添加数据项
defalutValueArr.insert("frist Value", at: 0)
//: ### 5.remove(at:)方法来移除数组中的某一项  removeLast()删除最后一项
defalutValueArr.remove(at: 0)
//: ### 6.遍历数组 for-in
print("______Arr for-in_______")
for items in defalutValueArr {
    print(items)
}
//: ### 7.使用enumerated()方法来进行数组遍历
print("______Arr enumerated(_______")
for (index,value) in defalutValueArr.enumerated() {
    print("\(index) *** \(value)")
}

//: ## Sets 集合是存储相同类型但是没有确定顺序的值。当集合元素顺序不重要时或者希望确保每个元素只出现一次时可以使用集合而不是数组。
//: ### 1.创建一个空的集合
var letters = Set<Character>()
letters.insert("a")
//: #### letters 现在含有1个 Character 类型的值
letters = []
//: #### 现在是一个空的 Set, 但是它依然是 Set<Character> 类型

//: ### 2.使用contains(_:)方法去检查Set中是否包含一个特定的值：
if letters.contains("a") {
    print("包含的")
}else{
    print("不包含")
}

//: ## 集合操作
var setOne:Set = [1, 3, 5, 7, 9]
var setTwo:Set = [0, 2, 4, 6, 8]
var setThree:Set = [2,3,5,7]
//: ### 1.使用intersection(_:) 取交集
print("______intersection(_:)_______")
print(setTwo.intersection(setThree))
//: ### 2.使用symmetricDifference(_:) 不是"交集"的部分的"和"
print("______symmetricDifference(_:)_______")
print(setTwo.symmetricDifference(setThree))
//: ### 3.使用union(_:) 并集
print("______union(_:)_______")
print(setTwo.union(setThree))
//: ### 4.使用subtracting(_:) 自己不是 "交集" 的部分
print("______subtracting(_:)_______")
print(setTwo.subtracting(setThree))

//: ## 集合成员关系和相等
let houseAnimals: Set = ["🐶", "🐱"]
let farmAnimals: Set = ["🐮", "🐔", "🐑", "🐶", "🐱"]
let cityAnimals: Set = ["🐦", "🐭"]

//: ### 1.使用“是否相等”运算符(==)来判断两个集合是否包含全部相同的值。
if houseAnimals == farmAnimals{
    print("相等")
}else{
    print("不相等")
}
//: ### 2.使用isSubset(of:)方法来判断一个集合中的值是否也被包含在另外一个集合中。
print("______isSubset(of:)_______")
print(houseAnimals.isSubset(of: farmAnimals))
//: ### 3.使用isSuperset(of:)方法来判断一个集合中包含另一个集合中所有的值。
print("______isSuperset(of:)_______")
print(farmAnimals.isSuperset(of: houseAnimals))
//: ### 4.使用isStrictSubset(of:)或者isStrictSuperset(of:)方法来判断一个集合是否是另外一个集合的子集合或者父集合并且两个集合并不相等。
print("______isStrictSubset(of:)/isStrictSuperset(of:)_______")
print(houseAnimals.isStrictSubset(of: farmAnimals))
print(farmAnimals.isStrictSuperset(of: houseAnimals))
//: ### 5.使用isDisjoint(with:)方法来判断两个集合是否"不含有"相同的值(是否没有交集)。 false 代表有交集
print("______isDisjoint(with:)_______")
print(farmAnimals.isDisjoint(with: houseAnimals))


//: ## 字典
//: ### 1.创建一个空的字典
var namesDic:[String:String] = ["nameOne":"zhaozhongpeng"]

//: 2.updateValue(_:forKey:)方法会返回对应值的类型的可选值。举例来说：对于存储String值的字典，这个函数会返回一个String?或者“可选 String”类型的值。如果有值存在于更新前，则这个可选值包含了旧值，否则它将会是nil。
print("______Dic updateValue(_:forKey:)_______")
if namesDic.updateValue("sunxiaofei", forKey: "nameOne") != nil {
    print("更新成功")
}

//: ### 3.removeValue(forKey:)方法也可以用来在字典中移除键值对。这个方法在键值对存在的情况下会移除该键值对并且返回被移除的值或者在没有值的情况下返回nil：
print("______Dic removeValue(forKey:)_______")
print(namesDic.removeValue(forKey: "nameOne"))
print(namesDic.removeValue(forKey: "nameOne"))

//: ### 4. 我们可以使用for-in循环来遍历某个字典中的键值对。每一个字典中的数据项都以(key, value)元组形式返回，并且我们可以使用临时常量或者变量来分解这些元组
print("______Dic for-in_______")
for (k,v) in namesDic {
    print(k + v)
}

//: ### 5.通过访问keys或者values属性，我们也可以遍历字典的键或者值
print("______Dic keys或者values_______")
namesDic["1qw2w"] = "123"
for k in namesDic.keys {
    print(k)
}
for v in namesDic.values {
    print(v)
}

